#include "OpenGLWidgetTextueMouseKey.h"
#include<QDebug>

#include<gl/GLU.h>
#include<glm/glm.hpp>
#include<glm/gtc/type_ptr.hpp>
#include<QCoreApplication>
#include<QBitmap>
#include<QKeyEvent>

#include"OpenGLUtil.h"

// 鼠标键盘控制视角。
// 鼠标滚轮：前进，后退
// 键盘上、下、左、右键：平移
// 鼠标拖动：旋转

static float vertices[] = {

	

	0.5f, 0.5f, 0.0f,  // top right
	0.5f,-0.5f, 0.0f, // bottom right
	-0.5f, -0.5f, 0.0f, // bottom left
	-0.5f, 0.5f, 0.0f, // top left

	0.5f, 0.5f, -0.5f,  // top right
	0.5f,-0.5f, -0.5f, // bottom right
	-0.5f, -0.5f, -0.5f, // bottom left
	-0.5f, 0.5f, -0.5f, // top left

	0.5f, 0.5f, 0.0f,  // top right
	0.5f,-0.5f, 0.0f, // bottom right
	0.5f,-0.5f, -0.5f, // bottom right
	0.5f, 0.5f, -0.5f,  // top right
	


};

static unsigned int indices[] = {
	0,1,2,3, // 四边形 
	4,5,6,7,
	8,9,10,11,

};

static float texCoordVertexs[] = {  // 图片的位置 坐上角为 （0，0），右下角为（1，1）
1,0, // 图片右上角
1,1, // 右下角
0,1, // 左下角
0,0, // 左上角

1,0, // 图片右上角
1,1, // 右下角
0,1, // 左下角
0,0, // 左上角

1,0, // 图片右上角
1,1, // 右下角
0,1, // 左下角
0,0, // 左上角
};

OpenGLWidgetTextureMouseKey::OpenGLWidgetTextureMouseKey(QWidget* parent) :QOpenGLWidget(parent)
{
	setFocusPolicy(Qt::FocusPolicy::ClickFocus);
}

OpenGLWidgetTextureMouseKey::~OpenGLWidgetTextureMouseKey()
{
	//makeCurrent();
	//glDeleteBuffers(1, &VBO);
	//glDeleteVertexArrays(1, &VAO);
	//glDeleteProgram(shaderProgram);
	//doneCurrent();
}

//void OpenGLWidgetTextureMouseKey::drawShape(Shape shape)
//{
//	_shape = shape;
//	update();
//}

void OpenGLWidgetTextureMouseKey::setWireFrame(bool wireFrame)
{
	// 在paintGL 函数以外的地方调用OpenGL函数没有意义，最终会被paintGL覆盖。所以必须以如下方式调用OpenGL函数。
	makeCurrent(); // --- 外部调用OpenGL函数前必须以 makeCurrent 函数开始
	if (wireFrame)
	{
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	}
	else
	{
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	}
	update();     // --- 外部调用OpenGL函数之后必须以 update 函数更新UI界面
	doneCurrent();// --- 外部调用OpenGL函数之后必须以 doneCurrent 函数结束
	//this->se
}
static GLuint texName;
void OpenGLWidgetTextureMouseKey::initializeGL()
{
	initializeOpenGLFunctions(); // 初始化opengl 相关的函数

	PrintVersion();
	
	QString imgPath = QCoreApplication::applicationDirPath() + "/../../resources/texture_test.png";
	QImage img(imgPath);
	QImage img2 = img.convertToFormat(QImage::Format::Format_RGB888);
	//img2 = img2.mirrored();

	/*if (!img2.save("d:/bbb.png"))
	{
		qDebug() << "save img2 error!";
	}*/
	int w = img2.width();
	int h = img2.height();
	int len = img2.width() * img2.height() * 3;

	uchar* data = new uchar[len];
	memcpy(data, img2.bits(), len);
	qDebug() << img2.format();
	glGenTextures(1, &texName);
	glBindTexture(GL_TEXTURE_2D, texName);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
	glGenerateMipmap(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, 0);

}

void OpenGLWidgetTextureMouseKey::resizeGL(int w, int h)
{
}

//static float eysX = 0;
//static float eysY = 0;
//static float eysZ = 1;
//static float centerX = 0;
//static float centerY = 0;
//static float centerZ = 0;
static float raduis = 1;

static glm::vec3 eyePos = {0,0,1};
static glm::vec3 centerPos = {0,0,0};
static glm::vec3 upPos = {0, 1, 0}; // 最后一位没有作用
static bool isPressed = false;
static QPoint lastPoint;

void OpenGLWidgetTextureMouseKey::mousePressEvent(QMouseEvent *event) {
	
	isPressed = true;
	lastPoint = event->pos();
	qDebug() << "mousePressEvent " << lastPoint;
}
void OpenGLWidgetTextureMouseKey::mouseReleaseEvent(QMouseEvent *event) {
	isPressed = false; update();
}
void OpenGLWidgetTextureMouseKey::mouseMoveEvent(QMouseEvent *event) {
	double xDiff = -(event->pos().x() - lastPoint.x()) * 1.0 / width();
	double yDiff = (event->pos().y() - lastPoint.y()) * 1.0 / height();
	QPoint diff = event->pos() - lastPoint;
	qDebug() << "event->pos() "  <<  event->pos();
	qDebug() << "lastPoint " << lastPoint;
	lastPoint = event->pos();

	///double r = 
	qDebug() << xDiff;
	qDebug() << yDiff;
	qDebug() << raduis;
	glm::vec3 v = centerPos - eyePos; // 视角方向向量
	glm::vec3 v1 = glm::cross(v, upPos); // 指向v的左侧向量
	//glm::vec3 v2 = glm::cross(v, v1); //指向v的上方向量


	float angle1 = std::atan(yDiff / raduis);
	glm::mat4x4 mat(1.0f);
	mat = glm::rotate(mat, angle1, v1); // 镜头上下旋转
	glm::vec3 v3 = mat*glm::vec4{ v,1 };

	float angle2 = std::atan(xDiff / raduis);
	glm::vec3 v4 = glm::cross(v3, v1); // 指向v3 的上方
	glm::mat4x4 mat1(1.0f);
	mat1 = glm::rotate(mat1, angle2, v4); // 镜头左右旋转
	glm::vec3 v5 = mat1*glm::vec4{ v3, 1 };


	centerPos = v5 + eyePos;
	
	qDebug() << " centerPos.x " << centerPos.x << " centerPos.y " << centerPos.y << " centerPos.z " << centerPos.z;
	qDebug() << " eyePos.x " << eyePos.x << " eyePos.y " << eyePos.y << " eyePos.z " << eyePos.z;

	//qDebug() << "rotate angle: " <<  angle;

	//glm::vec3 v = centerPos - eyePos ; // 视角方向向量
	//glm::vec3 v1 = {xDiff, yDiff, 0}; // 视角移动向量
	//qDebug() << "v1.x " << v1.x << " v1.y " << v1.y << " v1.z " << v1.z;
	//glm::vec3 v2 = v + v1;
	//qDebug() << "v2.x " << v2.x << " v2.y " << v2.y << " v2.z " << v2.z;
	//double a = std::sqrtf(v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
	//v2 = {v2.x/a, v2.y/a, v2.z/a};
	//centerPos = v2 + eyePos;
	//qDebug() << "v2.x " << v2.x << " v2.y " << v2.y << " v2.z " << v2.z;
	//qDebug() << " centerPos.x " << centerPos.x << " centerPos.y " << centerPos.y << " centerPos.z " << centerPos.z;
	//qDebug() << " eyePos.x " << eyePos.x << " eyePos.y " << eyePos.y << " eyePos.z " << eyePos.z;

	//v2 = v2.length();

	//float angle = std::atan();
	//glm::vec3 axis ; // 旋转轴
	//glm::mat4x4 mat(1.0f);
	//mat = glm::rotate(mat, angle, axis);

	//glm::vec3 newCenterPos = glm::vec4{ v,1 } *mat;
	//newCenterPos += eyePos;
	//qDebug() << "newCenterPos " << newCenterPos.x << " " << newCenterPos.y;
	//centerPos = newCenterPos;
	//glm::vec3 r = ;
	
	
}
void OpenGLWidgetTextureMouseKey::wheelEvent(QWheelEvent *event) {
	qDebug() << "wheel event";
	qDebug() << event->angleDelta();
	glm::vec3 v = centerPos - eyePos;
	v = { v.x / 10,v.y/ 10, v.z/ 10 };
	if (event->angleDelta().y() > 0)
	{
		eyePos += v;
		centerPos += v;

	}
	else
	{
		eyePos -= v;
		centerPos -= v;

	}
	update();
}

void OpenGLWidgetTextureMouseKey::keyPressEvent(QKeyEvent * event)
{
	float keySetp = -0.1;
	glm::vec3 v = centerPos - eyePos; // 视角方向向量
	glm::vec3 v1 = glm::cross(v, upPos); // 指向v的左侧向量
	double a = std::sqrt(v1.x*v1.x + v1.y* v1.y+ v1.z*v1.z);
	glm::vec3 v2 = {v1.x/a*keySetp,v1.y / a*keySetp,v1.z / a*keySetp }; // 左右偏移量
	glm::vec3 v3 = glm::cross(v, v1); //指向v的上方向量
	double b = std::sqrt(v3.x*v3.x + v3.y* v3.y + v3.z*v3.z);
	glm::vec3 v4 = { v3.x / b*keySetp,v3.y / b*keySetp,v3.z / b*keySetp }; // 上下偏移量
	

	if (event->key() == Qt::Key::Key_Right)
	{
		qDebug() << "right clicked";
		eyePos -= v2;
		centerPos -= v2;
	}

	if (event->key() == Qt::Key::Key_Left)
	{
		qDebug() << "right clicked";
		eyePos += v2;
		centerPos += v2;
	}

	if (event->key() == Qt::Key::Key_Up)
	{
		qDebug() << "right clicked";
		eyePos += v4;
		centerPos += v4;
	}

	if (event->key() == Qt::Key::Key_Down)
	{
		qDebug() << "right clicked";
		eyePos -= v4;
		centerPos -= v4;
	}
	update();
}

void OpenGLWidgetTextureMouseKey::paintGL()
{
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
	qDebug() << "paintGL";

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	//glTranslated(0, 0, 0);
	gluLookAt(eyePos.x, eyePos.y, eyePos.z, centerPos.x, centerPos.y, centerPos.z, upPos.x, upPos.y, upPos.z);


	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	float ratio = (GLfloat)(this->width()) / (GLfloat)(this->height());
	gluPerspective(100.0f, ratio, 0.1f, 2000.0f); // gluPerspective 与 gluLookAt 相互依赖，两个函数必须配对使用才有效果，否则无法显示。

	
	
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, vertices);

	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texName);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(2,GL_FLOAT,0, texCoordVertexs);

	//glDrawArrays(GL_TRIANGLES, 0 , 3);
	glDrawElements(GL_QUADS, 12,GL_UNSIGNED_INT , indices);

	glPopMatrix();
	//glMatrixMode(GL_MODELVIEW);
	//glPopMatrix();

}
